package team.hyznrj.studentsys.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.bson.types.ObjectId;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.github.pagehelper.PageHelper;
import com.mongodb.BasicDBObject;

import lombok.Data;
import team.hyznrj.studentsys.dao.mapper.QualityAchievementMapper;
import team.hyznrj.studentsys.dto.QualityAchievementDto;
import team.hyznrj.studentsys.dto.QualitySearchDto;
import team.hyznrj.studentsys.dto.StudentMessageSearchDto;
import team.hyznrj.studentsys.entity.DBPageMessage;
import team.hyznrj.studentsys.entity.QualityAchievement;
import team.hyznrj.studentsys.entity.QualityAchievementExample;
import team.hyznrj.studentsys.entity.QualityAchievementExample.Criteria;
import team.hyznrj.studentsys.entity.QualityAggregationEntity;
import team.hyznrj.studentsys.entity.QualityEntity;
import team.hyznrj.studentsys.entity.QualityMessage;
import team.hyznrj.studentsys.entity.QualityResultEntity;
import team.hyznrj.studentsys.entity.SGQEntity;
import team.hyznrj.studentsys.entity.SimpleQualityEntity;
import team.hyznrj.studentsys.enums.DataBaseOperateMethod;
import team.hyznrj.studentsys.enums.DataReportEnum;
import team.hyznrj.studentsys.exception.DataIllegalException;
import team.hyznrj.studentsys.exception.DataNullException;
import team.hyznrj.studentsys.service.QualityAchievementService;
import team.hyznrj.studentsys.service.StudentMessageService;
import team.hyznrj.studentsys.service.StudentMsgMapService;
import team.hyznrj.studentsys.utils.ValueUtil;

@Service
@Transactional
public class QualityAchievementServiceImpl implements QualityAchievementService {

	private static final double _0_00 = 0.00;
	private static final String _0 = "0";
	/**
	 * MongDB主键关键字
	 */
	@Value("${StudentMessageServicePrimaryKey}")
	private String PRIMARY_KEY;
	/**
	 * 学号值
	 */
	@Value("${StudentMessageSno}")
	private String STUDENT_MESSAGE_SNO;
	/**
	 * 结果集的分页名
	 */
	private static final String RESULT_PAGE_KEY="page";
	/**
	 * 排序SQL语句
	 */
	private static final String ORDER_CAUSE_SQL = "SNO ASC,ITEM ASC";
	/**
	 * 系等级
	 */
	private static final int PRO_LEVEL = 2;
	/**
	 * 模糊查询通配符
	 */
	private static final String PER_PATTERN = "%";
	

	/**
	 * 缓存
	 */
	@Autowired
	private StaticDatabasesValueCache cache;
	/**
	 * 操行分MAPPER
	 */
	@Autowired
	QualityAchievementMapper qualityMapper;
	/**
	 * 批处理
	 */
	@Autowired
	private SqlSessionTemplate sqlSessionTemplate;
	@Autowired
	private StudentMessageService stuService;
	@Autowired
	private StudentMsgMapService stuMsgMapService;

	/**
	 * DTO->ENTITY适配转换
	 * 
	 * @param record
	 * @return
	 */
	private QualityAchievement toQualityAchievement(QualityAchievementDto record) {
		if (record != null) {
			QualityAchievement result = new QualityAchievement();
			result.setFlag(record.getFlag());
			result.setNo(record.getNo());
			result.setSno(record.getSno());
			result.setItem(record.getItem());
			result.setProject(record.getProject());
			result.setValue(record.getValue());
			result.setProjectType(record.getProjectType());
			/**设置时间为当前服务器时间*/
			result.setCreateTime(new Date());
			String academicYears = record.getAcademicYears();
			if (!StringUtils.isEmpty(academicYears)) {
				Integer yearByValue = cache.getYearByValue(academicYears);
				result.setAcademicYears(yearByValue);
			}
			return result;
		}
		return null;
	}

	private boolean operateQualityReal(final QualityAchievement record, final DataBaseOperateMethod method,
			final String flag) {
		if (record != null) {
			record.setFlag(flag);
			record.setCreateTime(new Date());
			record.isLegal(method.equals(DataBaseOperateMethod.INSERT)
					|| method.equals(DataBaseOperateMethod.INSERT_AND_UPDATE));
			if (method.equals(DataBaseOperateMethod.INSERT)) {
				/**
				 * 插入单条数据，不考虑数据合法性(数据库约束)
				 */
				record.setNo(new ObjectId().toString());
				return qualityMapper.insert(record) > 0 ? true : false;
			} else if (method.equals(DataBaseOperateMethod.UPDATE)) {
				/** 按编号更新 */
				QualityAchievementExample example = new QualityAchievementExample();
				example.createCriteria().andNoEqualTo(record.getNo())
						.andFlagLike(ValueUtil.getFlag(flag, PRO_LEVEL) + PER_PATTERN);
				int value = qualityMapper.updateByExampleSelective(record, example);
				return value > 0 ? true : false;
			} else if (method.equals(DataBaseOperateMethod.DELETE)) {
				/** 按编号删除 */
				QualityAchievementExample example = new QualityAchievementExample();
				example.createCriteria().andNoEqualTo(record.getNo())
						.andFlagLike(ValueUtil.getFlag(flag, PRO_LEVEL) + PER_PATTERN);
				int value = qualityMapper.deleteByExample(example);
				return value > 0 ? true : false;
			} else if (method.equals(DataBaseOperateMethod.INSERT_AND_UPDATE)) {
				record.setNo(new ObjectId().toString());
				int result = -1;
				try {
					/**
					 * 插入失败，基本上是主键约束
					 */
					result = qualityMapper.insertSelective(record);
				} catch (Exception e) {
					result = qualityMapper.updateByPrimaryKey(record);
				}
				return result > 0 ? true : false;
			}
		}
		throw new DataNullException("操行分数据不能为空");
	}

	private int operateQualitiesReal(final List<QualityAchievement> records, final DataBaseOperateMethod method,
			final String flag) {
		if (records != null && records.size() > 0) {
			SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
			QualityAchievementMapper mapper2 = session.getMapper(QualityAchievementMapper.class);
			try {
				if (method.equals(DataBaseOperateMethod.INSERT)) {
					/**
					 * 插入数据，不考虑该数据是否存在
					 */
					for (QualityAchievement record : records) {
						record.setFlag(flag);
						record.setCreateTime(new Date());
						record.setNo(new ObjectId().toString());
						mapper2.insert(record);
					}
				} else if (method.equals(DataBaseOperateMethod.INSERT_AND_UPDATE)) {
					/**
					 * 插入或更新数据，如果需更新则按编号来更新
					 */
					for (QualityAchievement record : records) {
						record.setFlag(flag);
						record.setCreateTime(new Date());
						/**
						 * 如果不存在编号，则不需要在意是否需要更新（编号锁定）
						 */
						if (record.getNo() != null) {
							QualityAchievementExample example = new QualityAchievementExample();
							/** 按编号更新 */
							example.createCriteria().andNoEqualTo(record.getNo())
									.andFlagLike(ValueUtil.getFlag(flag, PRO_LEVEL) + PER_PATTERN);
							List<QualityAchievement> list = mapper2.selectByExample(example);
							if (list != null && list.size() > 0) {
								mapper2.updateByExampleSelective(record, example);
								continue;
							}
						}
						/**
						 * 如果主键存在(学号、加分项目、学年、学期 全匹配),也不需要插入 只需要更新 加分值或者加分类型即可
						 */
						if (mapper2.selectByPrimaryKey(record) != null) {
							mapper2.updateByPrimaryKeySelective(record);
							continue;
						}
						/** 否则插入数据，需设置编号 */
						record.setNo(new ObjectId().toString());
						mapper2.insert(record);
					}
				} else if (method.equals(DataBaseOperateMethod.UPDATE)) {
					/**
					 * 多条数据更新（按编号进行更新 : 不适合用联合主键）
					 */
					for (QualityAchievement record : records) {
						record.setCreateTime(new Date());
						record.setFlag(flag);
						QualityAchievementExample example = new QualityAchievementExample();
						/** 按编号更新 */
						example.createCriteria().andNoEqualTo(record.getNo())
								.andFlagLike(ValueUtil.getFlag(flag, PRO_LEVEL) + PER_PATTERN);
						mapper2.updateByExampleSelective(record, example);
					}
				} else if (method.equals(DataBaseOperateMethod.DELETE)) {
					/**
					 * 多个单条数据的删除（完全匹配学号、加分项目、学年、学期）
					 */
					for (QualityAchievement record : records) {
						mapper2.deleteByPrimaryKey(record);
					}
				} else if (method.equals(DataBaseOperateMethod.DELETE_ALONE)) {
					/**
					 * 多个单条数据的删除（只匹配 不为NULL的条件）
					 */
					for (QualityAchievement record : records) {
						QualityAchievementExample example = new QualityAchievementExample();
						Criteria criteria = example.createCriteria()
								.andFlagLike(ValueUtil.getFlag(flag, PRO_LEVEL) + PER_PATTERN);
						boolean flag1 = false;
						/* 按编号删除 */
						if (StringUtils.isEmpty(record.getNo())) {

							criteria.andNoEqualTo(record.getNo());
							flag1 = true;
						}
						/* 按学号删除 */
						if (StringUtils.isEmpty(record.getSno())) {
							criteria.andSnoEqualTo(record.getSno());
							flag1 = true;
						}
						/**
						 * 附加条件只能在 学号或者编号二者成立其一的情况下筛选 否则会出现删除大量无关信息
						 */
						if (flag1) {
							/* 按比赛/加分项目删除 */
							if (StringUtils.isEmpty(record.getProject())) {
								criteria.andProjectEqualTo(record.getProject());
							}
							/* 按类型删除 */
							if (StringUtils.isEmpty(record.getProjectType())) {
								criteria.andProjectTypeEqualTo(record.getProjectType());
							}
							/* 按学年编号删除 */
							if (record.getAcademicYears() != null) {
								criteria.andAcademicYearsEqualTo(record.getAcademicYears());
							}
							/* 按加分值删除 */
							if (record.getValue() != null) {
								criteria.andValueEqualTo(record.getValue());
							}
							/* 按学期删除 */
							if (record.getItem() != null) {
								criteria.andItemEqualTo(record.getItem());
							}
						}
						mapper2.deleteByExample(example);
					}
				}
				session.commit();
				return records.size();
			} catch (Exception e) {
				System.out.println(e);
				// session.rollback(); //ROLLBACK无效，直接加注解即可ROLLBACK
			} finally {
				session.close();
			}
		}
		throw new DataNullException("数据不合法");
	}

	@Override
	public List<QualityAchievement> selectByExample(final QualityAchievementExample example) {
		return qualityMapper.selectByExample(example);
	}

	@Override
	public List<QualityEntity> countDataByStuNo(final List<QualitySearchDto> stu, final String flag,
			final Map<String, SGQEntity> stuMessage) {
		List<QualityEntity> list = new ArrayList<>();
		
		/**
		 * 遍历数组
		 */
		for (QualitySearchDto dto : stu) {
			/**
			 * 虑空
			 */
			final String key = dto.getStuNo();
			final Integer years = dto.getAcademyYears();
			final Integer item = dto.getItem();
			if (!StringUtils.isEmpty(key)) {
				/**
				 * 取学号匹配的学生信息
				 */
				QualityAchievementExample example = new QualityAchievementExample();
				Criteria criteria = example.createCriteria();
				criteria.andSnoEqualTo(key);
				if (years != null && years > 0) {
					/** 按学年 */
					criteria.andAcademicYearsEqualTo(years);
				}
				if (item != null && item > 0) {
					/** 按学期 */
					criteria.andItemEqualTo(item);
				}
				/** 按学院/系 */
				criteria.andFlagLike(ValueUtil.getFlag(flag, PRO_LEVEL) + PER_PATTERN);
				List<QualityAchievement> messages = qualityMapper.selectByExample(example);
				if (messages != null && messages.size() > 0) {
					QualityEntity entity = new QualityEntity();
					/**
					 * 初始化学生学号
					 */
					entity.setSno(key);
					/**
					 * 初始化学期
					 */
					entity.setItem(item);
					/**
					 * 初始化学年
					 */
					String yearById = null;
					if (!StringUtils.isEmpty(years)) {
						yearById = cache.getYearById(years);
					}
					entity.setAcademic_year(yearById);
					/**
					 * 遍历成绩数据
					 */
					Map<String, QualityMessage> qualities = new HashMap<>();
					entity.setQualityMessages(qualities);
					for (int i = 0; i < messages.size(); i++) {
						QualityAchievement qualityAchievement = messages.get(i);
						/**
						 * 加分项目
						 */
						String project = qualityAchievement.getProject();
						/**
						 * 类型id
						 */
						String projectTypeId = qualityAchievement.getProjectType();
						//1
						/**
						 * 加分值
						 */
						Float value = qualityAchievement.getValue();
						if (!StringUtils.isEmpty(project) && !StringUtils.isEmpty(projectTypeId)
								&& !StringUtils.isEmpty(value)) {
							QualityMessage qualityMessage = null;
							if (qualities.containsKey(cache.getQualitiyTypeById(projectTypeId))) {
								qualityMessage = qualities.get(cache.getQualitiyTypeById(projectTypeId));
							} else {
								// 1
								qualityMessage = new QualityMessage();
								/** 设置编号 */
								qualityMessage.setTypeNo(projectTypeId);
								/** 设置加分项目名 */
								qualityMessage.setType(cache.getQualitiyTypeById(projectTypeId));
								//放回去
								qualities.put(cache.getQualitiyTypeById(projectTypeId), qualityMessage);
							}
							/** 加值 */
							project+=key+"#"+qualityAchievement.getAcademicYears()+"#"+qualityAchievement.getItem();
							qualityMessage.put(project, value);
						}
					}
					// 加入数组
					list.add(entity);
					if (stuMessage != null) {
						stuMessage.get(entity.getSno()).setQualityEntity(entity);
						// 这里不需要put回去，因为是地址引用
						// stuMessage.put(entity.getSno(), value)
					}
				}
			}
		}
		return list;
	}

	@Override
	public Map<String, Object> selectByDetail(final StudentMessageSearchDto dto) {
		Map<String, Object> result = new HashMap<>();
		List<QualityResultEntity> data = new ArrayList<>();
		result.put("result", data);
		if (dto != null && !StringUtils.isEmpty(dto.getFlag())) {
			/**
			 * 不对学号分页
			 */
			dto.setOpenPage(false);
			/**
			 * 查询学生基本信息
			 */
			List<BasicDBObject> studentsSno = stuService.getStudentsSno(dto);
			Map<String, BasicDBObject> stuMap = new HashMap<>();
			List<String> snoList = new ArrayList<>();
			/** value->id映射 */
			Map<String, String> idMap = stuMsgMapService.getAllMsgIdMap(dto.getFlag());
			/** 将学号放入数组，方便后面进行数据库查询,另加入映射Map,为后面装载对象做准备 */
			if (studentsSno != null && studentsSno.size() > 0) {
				for (BasicDBObject obj : studentsSno) {
					String sno = obj.getString(idMap.get(STUDENT_MESSAGE_SNO));
					snoList.add(sno);
					stuMap.put(sno, obj);
				}
			}
			/** MYSQL数据库查询 */
			
			QualityAchievementExample example = new QualityAchievementExample();
			Criteria criteria = example.createCriteria();
			criteria.andFlagLike(ValueUtil.getFlag(dto.getFlag(), PRO_LEVEL) + PER_PATTERN);
			if (snoList.size() > 0) {
				criteria.andSnoIn(snoList);
			}
			/** 遍历year数组（可能存在多个year） */
			List<String> year = dto.getAcademic_year();
			List<Integer> yearVals = new ArrayList<>();
			if (year != null) {
				for (String str : year) {
					if (!StringUtils.isEmpty(str)) {
						Integer value = cache.getYearByValue(str);
						yearVals.add(value);
					}
				}
				criteria.andAcademicYearsIn(yearVals);
			}
			/** 遍历可能存在的学期 */
			List<Integer> item = dto.getItem();
			if (item != null) {
				for (Integer i : item) {
					if (i != 1 && i != 2) {
						throw new DataIllegalException("学期参数不合法");
					}
				}
				criteria.andItemIn(item);
			}
			/** 按学号、学分排下序 */
			example.setOrderByClause(ORDER_CAUSE_SQL);
			if (dto.getPageIndex() != null && dto.getPageSize() != null) {
				/**分页会对下一条SQL起作用，所以只能放在前面*/
				int count = qualityMapper.countByExample(example);
//				result.put("page", size);
				result.put(RESULT_PAGE_KEY, new DBPageMessage(dto.getPageIndex(), dto.getPageSize(), count));
				PageHelper.startPage(dto.getPageIndex(), dto.getPageSize(), true);
			}
			/** 查询数据库，并封装对象 */
			List<QualityAchievement> list = qualityMapper.selectByExample(example);
			for (QualityAchievement quality : list) {
				QualityResultEntity entity = new QualityResultEntity();
				entity.setProject(quality.getProject());
				entity.setProjectType(cache.getQualitiyTypeById(quality.getProjectType()));
				entity.setValue(quality.getValue());
				entity.setItem(quality.getItem());
				entity.setAcademicYears(cache.getYearById(quality.getAcademicYears()));
				entity.setStudentBasicMessageValue(stuMap.get(quality.getSno()), idMap);
				data.add(entity);
			}
			return result;
		}
		throw new DataNullException("传入数据为空");
	}

	@Override
	public Map<String, Object> selectBySimple(StudentMessageSearchDto dto) {
		Map<String, Object> result = new HashMap<>();
		if (dto != null && !StringUtils.isEmpty(dto.getFlag())) {
			dto.setOpenPage(true);
			/**
			 * 查询学生基本信息
			 */
			List<BasicDBObject> studentsSno = stuService.getStudentsSno(dto);
			Map<String, QualityAggregationEntity> data = new HashMap<>();

			Map<String, BasicDBObject> stuMap = new HashMap<>();
			List<String> snoList = new ArrayList<>();
			/** value->id映射 */
			Map<String, String> idMap = stuMsgMapService.getAllMsgIdMap(dto.getFlag());
			/** 将学号放入数组，方便后面进行数据库查询,另加入映射Map,为后面装载对象做准备 */
			if (studentsSno != null && studentsSno.size() > 0) {
				for (BasicDBObject obj : studentsSno) {
					String sno = obj.getString(idMap.get(STUDENT_MESSAGE_SNO));
					snoList.add(sno);
					stuMap.put(sno, obj);
					QualityAggregationEntity tmp = new QualityAggregationEntity();
					tmp.setStudentBasicMessageValue(stuMap.get(sno), idMap);
					Map<String, String> quality = new HashMap<>();
					tmp.setQuality(quality);
					data.put(sno, tmp);
				}
			}
			/** 如果需要分页，则进行分页，否则不分页 */
			if (dto.getPageIndex() != null && dto.getPageSize() != null) {
				long count = stuService.getStudentsSnoCount(dto);
				result.put(RESULT_PAGE_KEY, new DBPageMessage(dto.getPageIndex(), dto.getPageSize(), count));
			}
			/** MYSQL数据库查询 */
			QualityAchievementExample example = new QualityAchievementExample();
			Criteria criteria = example.createCriteria();
			criteria.andFlagLike(ValueUtil.getFlag(dto.getFlag(), PRO_LEVEL) + PER_PATTERN);
			if (snoList.size() > 0) {
				criteria.andSnoIn(snoList);
			}
			/** 遍历year数组（可能存在多个year） */
			List<String> year = dto.getAcademic_year();
			List<Integer> yearVals = new ArrayList<>();
			if (year != null) {
				for (String str : year) {
					if (!StringUtils.isEmpty(str)) {
						Integer value = cache.getYearByValue(str);
						yearVals.add(value);
					}
				}
				criteria.andAcademicYearsIn(yearVals);
			}
			/** 遍历可能存在的学期 */
			List<Integer> item = dto.getItem();
			if (item != null) {
				for (Integer i : item) {
					if (i != 1 && i != 2) {
						throw new DataIllegalException("学期参数不合法");
					}
				}
				criteria.andItemIn(item);
			}
			/** 按学号、学分排下序 */
			example.setOrderByClause(ORDER_CAUSE_SQL);
			/** 查询数据库，并封装对象 */
			Map<String, Double> tmpVal = new HashMap<>();
			List<SimpleQualityEntity> selectBySimple = qualityMapper.selectBySimple(example);
			for (SimpleQualityEntity entity : selectBySimple) {
				String sno = entity.getSno();
				QualityAggregationEntity obj = data.get(sno);
				Map<String, String> quality = obj.getQuality();
				String key = cache.getQualitiyTypeById(entity.getProjectType());
				Double value = entity.getValue();
				tmpVal.put(key, tmpVal.getOrDefault(key, _0_00)+value);
				quality.put(key, tmpVal.get(key).toString());
				//可能存在2个学期一起加的情况，所以要加和运算
//				quality.put(key,(entity.getValue()+Double.valueOf(quality.getOrDefault(key, _0)).toString()));
			}
			result.put("result", data.values());
			return result;
		}
		throw new DataNullException("传入数据为空");
	}

	@Override
	@Transactional
	public boolean operateQuality(QualityAchievementDto record, DataBaseOperateMethod method, String flag) {
		return operateQualityReal(toQualityAchievement(record), method, flag);
	}
	@Override
	public int operateQualities(List<QualityAchievementDto> records, DataBaseOperateMethod method, String flag) {
		List<QualityAchievement> result = new ArrayList<>();
		for (int i = 0; i < records.size(); i++) {
			result.add(toQualityAchievement(records.get(i)));
		}
		return operateQualitiesReal(result, method, flag);
	}

	@Override
	public int deleteMulityQualities(List<String> no, String flag) {
		if (no != null && no.size() > 0) {
			for (String str : no) {
				if (StringUtils.isEmpty(str)) {
					throw new DataNullException("删除的ID为空");
				}
			}
			QualityAchievementExample example = new QualityAchievementExample();
			example.createCriteria().andNoIn(no).andFlagLike(ValueUtil.getFlag(flag, PRO_LEVEL) + PER_PATTERN);
			int i = qualityMapper.deleteByExample(example);
			return i;
		} else {
			throw new DataNullException("删除的ID为空");
		}
	}
	@Override
	public List<QualityAchievement> getQualityAchievementByConditions(List<String> ids, String academyYear,
			Integer item) {
		/** 查询条件 */
		QualityAchievementExample example = new QualityAchievementExample();
		Criteria criteria = example.createCriteria();
		/**
		 * 获取学年
		 */
		Integer yearByValue = cache.getYearByValue(academyYear);
		/**
		 * 获取学期
		 */
		if (item != null && item != 1 && item != 2) {
			throw new DataIllegalException("学期(" + item + ")不合法");
		} else {
			/** 按学期查 */
			if (item != null) {
				criteria.andItemEqualTo(item);
			}
		}
		/** 按学年查 */
		if (!StringUtils.isEmpty(yearByValue)) {
			criteria.andAcademicYearsEqualTo(yearByValue);
		}
		criteria.andSnoIn(ids);
		List<QualityAchievement> selectByExample = qualityMapper.selectByExample(example);
		return selectByExample;
	}

	@Override
	@Transactional
	public String addMsgs(QualityAchievementDto record, String flag) {
		List<String> snoList = record.getSnoList();
		record.setFlag(flag);
		if(snoList!=null&&snoList.size()>0){
			for(int i=0;i<snoList.size();i++){
				record.setNo(new ObjectId().toString());
				record.setSno(snoList.get(i));
				QualityAchievement achievement = toQualityAchievement(record);
				try {
					/**
					 * 插入失败，基本上是主键约束
					 */
					qualityMapper.insertSelective(achievement);
				} catch (Exception e) {
					System.out.println(e);
					qualityMapper.updateByPrimaryKey(achievement);
				}
			}
		}else{
			throw new DataNullException("操作的学号不能为空");
		}
		return "添加成功";
	}
}
